package week4th.jsjf;

import week4th.jsjf.exceptions.ElementNotFoundException;
import week4th.jsjf.exceptions.EmptyCollectionException;

import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

public abstract class ArrayList<T> implements ListADT<T>, Iterable<T>
{
    private final static int DEFAULT_CAPACITY = 100;
    private final static int NOT_FOUND = -1;
	
    protected int rear;
    protected T[] list;
    protected T[] alist;
	protected int modCount;

    public ArrayList()
    {
        this(DEFAULT_CAPACITY);
    }

    public ArrayList(int initialCapacity)
    {
        rear = 0;
        list = (T[])(new Object[initialCapacity]);
		modCount = 0;
    }

    protected void expandCapacity()
    {
        T[] larger = (T[]) (new Object[size() * 2]);
        for (int scan = 0; scan < modCount; scan++) {
            larger[scan] = list[scan];
        }
        rear = size();
        list = larger;
    }

    public T removeLast() throws EmptyCollectionException
    {
        int i =0;
        while (list[i] != null){
            i++;
        }
        list[i - 1] = null;
        rear--;
        return null;
    }

    public T removeFirst() throws EmptyCollectionException {
        for (int i = 0; i < size(); i++){
            alist[i]=list[i + 1];
        }
        list=alist;
        rear--;
        return null;
    }

    public T remove(T element)
    {
        T result;
        int index = find(element);

        if (index == NOT_FOUND)
            throw new ElementNotFoundException("ArrayList");

        result = list[index];
        rear--;

        for (int scan=index; scan < rear; scan++)
            list[scan] = list[scan+1];
 
        list[rear] = null;
		modCount++;

        return result;
    }

    public T first() throws EmptyCollectionException
    {
        return list[0];
    }

    public T last() throws EmptyCollectionException
    {
        int i = 0;
        while (list[i] != null){
            i++;
        }
        return list[i-1];
    }

    public boolean contains(T target)
    {
        return (find(target) != NOT_FOUND);
    }

    private int find(T target) {
        int scan = 0; 
		int result = NOT_FOUND;
 
        if (!isEmpty())
            while (result == NOT_FOUND && scan < rear)
                if (target.equals(list[scan]))
                    result = scan;
                else
                    scan++;

        return result;
    }

    public boolean isEmpty() {
        if (list[0] == null)
            return true;
        else
            return false;
    }

    public int size()
    {
        return rear;
    }

    public String toString() {
        String result="";
        for (int i = 0; i < size(); i++){
            result += list[i] + " " + "\n";
        }
        result = result.substring(0, result.length() - 1);
        return result;
    }

    public Iterator<T> iterator()
    {
        return new ArrayListIterator();
    }

	private class ArrayListIterator implements Iterator<T>
	{
		int iteratorModCount;
		int current;

		public ArrayListIterator()
		{
			iteratorModCount = modCount;
			current = 0;
		}

		public boolean hasNext() throws ConcurrentModificationException
		{
			if (iteratorModCount != modCount)
				throw new ConcurrentModificationException();
			
			return (current < rear);
		}

		public T next() throws ConcurrentModificationException
		{
			if (!hasNext())
				throw new NoSuchElementException();
			
			current++;
			
			return list[current - 1];
		}

		public void remove() throws UnsupportedOperationException
		{
			throw new UnsupportedOperationException();
		}
		
	}	
}
